#ifndef CLAM_H
#define CLAM_H

/******************************************************************N
                          clam.h
RW - tolerance
R -  int *bands
R -  int currentctg
R - struct contig *root, *clhigh
R - CLONE acedata
R - CONTIGDATA contigs
       contigs[currentctg].count

30jul02 useREP (fred)
*******************************************************************/
#include "fpp.h"
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>

#ifdef SUN
int time(), strftime();
#endif

#define graphQuery messQuery

//The default size for the number of F+ anf F- clones
//for the simulation option
#define PARALLEL_CUTOFF 1000
#define DO_SHARED_NTRIES(num_clones) ((num_clones * Pz.bestInt) > PARALLEL_CUTOFF)

#ifdef SOLARIS
   typedef int u_int32_t;
#endif

#define Outlog {if (Pz.logFlag && Zlogfp!=NULL) {fprintf(Zlogfp,"%s",ZBuf); fflush(Zlogfp);} if (Pz.stdFlag) {printf("%s",ZBuf);}}

#define NOLAP "Q"
/**
enum Colour    {WHITE, BLACK, LIGHTGRAY, DARKGRAY,
                RED, GREEN, BLUE,
                YELLOW, CYAN, MAGENTA,
                LIGHTRED, LIGHTGREEN, LIGHTBLUE,
                DARKRED, DARKGREEN, DARKBLUE,
                PALERED, PALEGREEN, PALEBLUE,
                PALEYELLOW, PALECYAN, PALEMAGENTA,
                BROWN, ORANGE, PALEORANGE,
                PURPLE, VIOLET, PALEVIOLET,
                GRAY, PALEGRAY,
                CERISE, MIDBLUE,
**/
#define CLAM PURPLE
#define CLAM_WEAK VIOLET
#define CLAM_PARENT PALEMAGENTA
#define CLAM_CLONE PALEBLUE

#define  BIG_NEG_NUM -99999

           /* values of ZZ.matrix[i].cbmap, if not set number */
#define ZSET -1
#define ZIGNORED -3
#define ZNOT_USED -5

         /* assigned to ZZ.matrix[i].mtype */
#define IAM_MOM 32
#define IAM_NOTHING 0
#define IAM_CHILD 1
#define IAM_EXACT 5
#define IAM_APPROX 9
           /* assigned to high_match */
#define QALIGN 1

#define In_Zset(c) (ZZ.matrix[c].pick != -1)
#define EndClone(clp, i) (clp->x-Pz.fromendInt <= contigs[i].left || \
                          clp->y+Pz.fromendInt >= contigs[i].right)
#define IsBuried(nb) (nb - Sz.match <=  (int) ((Pz.burFlt * (double) nb)))
#define IsZChild(i) (ZZ.matrix[i].mtype==IAM_EXACT || ZZ.matrix[i].mtype==IAM_APPROX)
#define Ztol(b1, diff) (!Proj.variable ? (abs(diff) <= Pz.tol) :  Zbcm(b1,diff))
#define Zgtol(b1) (!Proj.variable ? Pz.tol :  Zget_tol(b1))

enum {Calc, Build, IBC, Select, Again, Fp_order, Gel_order, Add, DQ, NoQ, NoCB, EndMerge};

  /**--------------- clam--------------- **/
void EvalCtgDisplay(), CBCtgDisplay(), EditCtgDisplay(), ClamCtgDisplay2();
struct contig *ZZp();

  /**--------------- score ---------------**/

/* alot of structures for the CpM - sness added CpMtmp */
#define MAX_CpM 4
struct CpMstruct {
  int nm, bd_nm;
  double cut, bd_cut;
};
struct CpMtable {
  char nmText[10], cutText[10];
  int nmBox, cutBox;
  int cnt;
};
struct CpMvar {
  BOOL autoFlag;
  int maxCpM;
  BOOL useFlag;
  BOOL usePCR, useYBP, useREP;
};
struct Buildvar {
  struct mytime date;
  double cutoff;
  int maxCpM;
  BOOL useFlag;
  BOOL usePCR, useYBP, useREP;
};

struct tmpCz {
   char clone[CLONE_SZ+1], parent[CLONE_SZ+1], fpnum[CLONE_SZ+1];
   char btype[10];
   int left, right;
   int start, nbands;
   int len, ctg;
   int cin;
#ifdef PARALLEL
   int* coords;
   int localCoords[NBANDS]; /* If you need a local copy, use this */
#else
   int coords[NBANDS];
#endif
};

/* This will copy the bands into localCoords and then set coords to point at
 * localCoords. So, a loadCzfast followed by a copyLocalCz will look exactly
 * like the old format: you can use local state in the bands.
 * Otherwise, loadCzfast will be much faster. :-)
 */
void copyLocalCz(struct tmpCz* local);

struct tmpSz {
   int ctg, tol;
   int olap, match, mark;
   float newMatch;
   int burdiff, olapdiff;
   double prob;
   char msg1[32], msg2[32];
   int diff[NBANDS];
   int total;
};

typedef enum {AGAROSE = 0, HICF = 1} fp_class_t;

/* assorted global variables used by the clam routines */
struct tmpPz { /* 1st set saved in fpc file */
   int tol;
   int fromendInt, minspanInt, seq_fromendInt, seq_minspanInt;
   int mergeMatches;
   float burFlt;
   double cutFlt;
   int diffInt, killInt;
   int logFlag, stdFlag;
   int bestInt;
   int minVal, maxVal;  /* min-max size of bands */
   int minBands;        /* minimal number of bands */

   int seqFlag;
   int autoaddFlag;
   int automergeFlag;
   int adjust;
   float gap;    /* CBmap params */
   float p_align;       /* percent aligned */
   int ctg, offset;
   int ok_olap;
   int useSz;
   int DQnumq;         /* DQer - cari 12/12/03 */
   int DQstep;         /* DQer - cari 12/12/03 */
   int DQusePct;       /* if 1, then DQnumq is a percent WN 02/04*/
   int DQsplit;        /* if 1, split all, else try to join cari 05/05 */
   int precompute;     /* precompute matrix of Sulston scores */
   int rebuild;        /* 1 do Q eq '-', else do Q eq '~' */
   fp_class_t fp_class;
};

void Zsulston(), Zgetmatch(); /* no args; C1z and C2z input, Sz output */

  /** ---------------build ---------------**/
#define HANG 100

struct Zworking_set {
   int ctg;
                   /* calculated during N tries */
   int n_Qs;
   float score, avg, low;
                    /* calculated during assign_clones_to_cbmaps */
   struct Zset_csort {
        int i, left;
   } *csort;
   int n_clone;
                    /* structures used in cb_assemble and cleared for each Ntries*/
   int n_added_clone;
   struct Zset_band
   { int high, low, total, avg;
     int zap, max;          /* working bit */
     int cnt, nocnt;
     int *clone, *val;
   } *band, *root;
   int n_band, max_band, leftb, rightb;
   int far_leftb, far_rightb;

   struct Zset_group
   { int leftb, rightb;
   } *group;
   int n_group, max_group;

   int hang_left[HANG], hang_right[HANG];
};
typedef struct Zworking_set ZSETZ;

struct Zpriority_queue {
   int score, fstbg, lastbg, parent;
   int C;
};
typedef struct Zpriority_queue ZPQZ;
ZPQZ *popZpq();
ZPQZ *insertZpq();

  /** ---------------sparse ---------------**/
struct ZSparse_node {
   int i1, i2;
   unsigned short int exponent, match;
   int next;      /* index into pool */
};
#define CLP(i) arrp(acedata, ZZ.matrix[i].cin, CLONE);
struct ZSparse_matrix {
   int cbmap;          /* set on first call to Greedy */
     /* not changed after initial setting */
   int nbands;       /* number of bands */
   int cin;          /* index into CLONE */
     /* reset after each of the N tries */
   int high_match, save_high_match;   /* candidate parent */
   int mtype, save_mtype;             /* parent or child in cbmap */
     /* reset in Again if cycle through all clones */
   int grand, save_grand;             /* Overall score */
     /* zero'ed out after each of the N tries */
   int cbQ;             /* Q clone ADD */
   int pick;            /* order the clones where picked for cbmap */
   int leftb, rightb;
   int *extra, n_extra, max_extra;
   int n_cb, *cb_index;
     /* for CBmaps display */
   int box, ebox;
     /* Values linking into pool of nodes */
   int first;            /* sparse; into pool */
   int last;		 /* added gaurav 12/03/03; index of last; into pool */
#ifdef PARALLEL
   pthread_mutex_t lock; /* Locks all the properties here and corresponding nodes in the pool */
   int nextQueued; /* Used in parrallel version to keep queues */
#endif
};

struct ZSparse_instance {
   char name[20];
   int  size, max, num; /* size of matrix, size of pool, used pool nodes */
   int ctg, type;  /* 0 - single, 1 - all, 2 - partial ctg, 3 - all ctg */
   int tol, band;
   double cut, cutOK;
   struct ZSparse_matrix *matrix;
   struct ZSparse_node *pool;
   struct ZSparse_matrix **threadMatrix;
   struct ZSparse_node   **threadPool;
   int *threadSize, *threadMax, *threadNum; /* FOR EACH THREAD: size of matrix,
   					      size of pool, used pool nodes */
   sem_t mutex;
#ifdef PARALLEL
   pthread_mutex_t lock; /* lock all matrix top level properties */
#endif
};
typedef struct ZSparse_node ZNODE;
typedef struct ZSparse_matrix ZMATRIX;
typedef struct ZSparse_instance ZINSTANCE;

int Zcreate_node(int i);
int Zcreate_instance();      /* name, &Sinstance and size */
void Zdestroy_instance();    /* &Sinstance */
void Zactivate_instance();   /* &Sinstance */
void Zdelete_node();         /* i,j  */
ZNODE *Ztraverse();          /* i */
ZNODE *Zif_exist();          /* i, j */
void Zcopy_node();           /* (&new, &old) */
void Zdump_all(), Zdump_node(); /* no args; msg, node */


int loadCzfast(struct tmpCz* Cx, int cin);

  /** ---------------general--------------- **/
/* cari 12/19/03 - add NOMEM2a and NOMEM3a */
#define NOMEM2(ptr, msg) {if (ptr==NULL) {fprintf(stderr,\
     "*** Error: cannot alloc memory at %s\n",msg); return;}}
#define NOMEM2a(ptr, msg, orig, new) {if (ptr==NULL) {fprintf(stderr,\
     "*** Error: cannot alloc memory at %s Original size: %d Realloc %d\n",msg, orig, new); return;}}
#define NOMEM3(ptr, msg, rc) {if (ptr==NULL) {fprintf(stderr,\
     "*** Error: cannot alloc memory at %s\n",msg); return rc;}}
#define NOMEM3a(ptr, msg, rc, orig, new) {if (ptr==NULL) {fprintf(stderr,\
     "*** Error: cannot alloc memory at %s Original Size %d Realloc %d\n",msg, orig, new); return rc;}}
#define ZFREE(ptr,msg) if (ptr!=NULL) {free(ptr); ptr=NULL; }
#define ZALLOC(ptr,size) ((ptr==NULL) ? malloc(size) : realloc(ptr, size))

 /** ---------------all clam globals ---------------**/
#ifdef ZZTOP
 int LastCB=0;
 int PRTMESS=1, Zbatch_flag=0;
 struct tmpCz C1z, C2z;
 struct tmpSz Sz;
 struct tmpPz Pz;
 Graph g9a = 0, g9b = 0, g9c = 0, g99 = 0, grule=0; /* g99=cbmap, grule= rule menu */
 FILE *Zlogfp= NULL;
 char ZBuf[512];
 struct tmpPz Pz = {-1, 0, 0, 0, 0.0, 0.0, 0, -1, 0, 1, 0, 0, 0, 0};

 ZINSTANCE ZZ= {" ", 0, 0, 0, 0,  0,0, 0, 0.0, 0.0, NULL, NULL};
 ZSETZ *Zset;
 int n_Zpq=0, max_Zpq=0;
 ZPQZ *Zpq;
 int n_Zset=0, max_Zset=0;
 char Fn[20];
 int Ignored_clones=0;
 int NoPop=0, ZS=0, Zadd=0, Zsort=0, Ztrace=0, Zorder=0, Zstep=0, Zpick=0;
 int qstuff=0;           /*efriedr 12/6/01*/
 int qstuff_nosplit=0;   /*efriedr 12/19/01*/
 int Zlastshow;          /* unburry all in next.c will change this */
 char CpMtype[2][5] = {"", " CpM"};
 struct CpMvar Cp;
 struct Buildvar Bd;
 struct CpMstruct CpM[MAX_CpM];
 struct CpMtable  CpMTbl[MAX_CpM];
#else
 extern struct CpMstruct CpM[MAX_CpM];
 extern struct CpMtable  CpMTbl[MAX_CpM];
 extern char CpMtype[2][5];
 extern struct CpMvar Cp;
 extern struct Buildvar Bd;
 extern int LastCB;
 extern int PRTMESS, Zbatch_flag;
 extern struct tmpCz C1z, C2z;
 extern struct tmpSz Sz;
 extern struct tmpPz Pz;
 extern Graph g9a, g9b, g9c, g99, grule;
 extern ZINSTANCE ZZ;
 extern ZSETZ *Zset;
 extern int n_Zpq, max_Zpq;
 extern ZPQZ *Zpq;
 extern int n_Zset, max_Zset;
 extern int NoPop, ZS, Zadd, Zsort, Ztrace, Zorder, Zstep, Zpick;
 extern int qstuff;   /*efriedr 12/6/01*/
 extern int qstuff_nosplit;   /*efriedr 12/19/01*/
 extern char Fn[20];
 extern FILE *Zlogfp;
 extern char ZBuf[512];
 extern int Ignored_clones;
 extern int Zlastshow, Zrule_grand,  Zrule_sim, Zrule_kill;
 extern int Zselect_trace;
#endif

/* This structure is used for parallelizing the "n tries" in Do_BestOf */
/* This has the per thread information */
struct Ntries_thread
{
 int save_c,save_j;
 int ntries; /* Number of tries on the thread */
 float low,save_score,avg_score;
 unsigned int pid; /*Process id of the thread*/
};

/* The following data structures are needed for the simulations */
int false_neg ;
int false_pos ;
sem_t false_pos_mutex;
sem_t false_neg_mutex;
int num_gaps;

#endif // CLAM_H
